home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume2
/
libraris
/
gimme.5
< prev
next >
Wrap
Text File
|
1988-12-02
|
47KB
|
1,838 lines
Path: xanth!mcnc!gatech!bloom-beacon!mit-eddie!ll-xn!adelie!infinet!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v02i078: gimme.lib - misc library routines, Part05/07
Message-ID: <10416@swan.ulowell.edu>
Date: 2 Dec 88 01:02:33 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 1827
Approved: page@swan.ulowell.edu
Submitted-by: oscvax!jan@uunet.UU.NET (Jan Sven Trabandt)
Posting-number: Volume 2, Issue 78
Archive-name: libraries/gimme.5
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# globals.c
# graph.c
# inputhand.c
# intuistuff.c
# keyboard.c
# memchain.c
# menu.c
# menustuff.c
# message.c
# This archive created: Thu Dec 1 19:52:10 1988
cat << \SHAR_EOF > globals.c
/*
* FILE: globals.c
* Some global declarations.
* This allows inclusion of <gimmelib/gimmeall.h> without linking in entire
* files containing global variables unnecessarily.
*
* Public Domain, but keep my name in it as the original author.
* 31-Aug-88 Jan Sven Trabandt first release version
*/
#define I_AM_GIM_GLOBALS
#include "gimmelib/requester.h"
#include "gimmelib/scrollbar.h"
/* generally usefull stuff */
struct TextAttr gimMyFont = {
(STRPTR) "topaz.font",
TOPAZ_EIGHTY,
FS_NORMAL,
FPF_ROMFONT
};
/* for requester.c */
UBYTE *gimAutReqPostext = (UBYTE *) GAR_POSTEXT;
UBYTE *gimAutReqNegtext = (UBYTE *) GAR_NEGTEXT;
/* for scrollbar.c */
USHORT gimDataOneScrollUp[] = {
0xffff,
0xffff,
0xfe7f,
0xfdbf,
0xfbdf,
0xf7ef,
0xeff7,
0xdffb,
0xffff
};
USHORT gimDataOneScrollDown[] = {
0xffff, 0xdffb, 0xeff7, 0xf7ef, 0xfbdf,
0xfdbf, 0xfe7f, 0xffff, 0xffff
};
USHORT gimDataOneScrollLeft[] = {
0xffff, 0xffcf, 0xff3f, 0xfcff, 0xf3ff,
0xfcff, 0xff3f, 0xffcf, 0xffff
};
USHORT gimDataOneScrollRight[] = {
0xffff, 0xf3ff, 0xfcff, 0xff3f, 0xffcf,
0xff3f, 0xfcff, 0xf3ff, 0xffff
};
SHAR_EOF
cat << \SHAR_EOF > graph.c
/*
* FILE: graph.c
* Support routines for creating and manipulating graphs.
*
* Public Domain, but keep my name in it as the original author.
* 31-Oct-88 Jan Sven Trabandt added to gimme.lib
*/
#define I_AM_GRAPH
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/graph.h"
#include "gimmelib/postext.h"
#include <clib/macros.h>
/* macros for internal scaling */
#define SCALEUP(x) ((long)(x) << SCALE) /* x * 2^SCALE */
#define SCALEDN(x) ((long)(x) >> SCALE) /* x / 2^SCALE */
/* macros to translate pixel offset from origin to pixel offset in rastport */
#define TRANSX(gr,off) ((short)((gr)->X.origin + (off)))
#define TRANSY(gr,off) ((short)((gr)->Y.origin - (off)))
/* leeways for titles */
#define XLEEWAY 4
#define YLEEWAY 3
#define TOLERANCE 2 /* pixel tolerance for fancy auto label */
/* internal flags for graphWriteLabel */
#define GWL_RESERVED_VAL (0x0000ffffL) /* lower short reserved for value */
#define GWL_NO_HIGH (1L << 16) /* for internal use only!! */
/* forward declarations */
static SHORT coordToOffset();
static SHORT offsetToCoord();
static VOID initAxis();
static SHORT updateCoord();
static VOID doBlock();
GRAPH *gimmeGraph( newgr, bm, areainfo, tmpras )
register NEWGRAPH *newgr;
struct BitMap *bm;
struct AreaInfo *areainfo;
struct TmpRas *tmpras;
{
register GRAPH *gr;
void *mymh = NULL;
UBYTE *raster;
SHORT width, height;
#ifdef GIMME_WIMPY
if( !newgr ) {
return( NULL );
}
#endif
if( !bm && (!newgr->rp || !newgr->rp->BitMap) ) {
return( NULL );
}
gr = (GRAPH *) chainAllocMem( &mymh, (ULONG)sizeof(GRAPH),
MEMF_PUBLIC | MEMF_CLEAR );
if( !gr ) {
return( NULL );
}
if( !newgr->rp ) {
InitRastPort( &gr->rp );
} else {
gr->rp = *newgr->rp; /* copy struct */
if( newgr->rp->Layer ) {
gr->rp.Layer = chainAllocMem( &mymh, (ULONG)sizeof(struct Layer),
MEMF_PUBLIC | MEMF_CLEAR );
if( !gr->rp.Layer ) {
chainFreeMem( mymh );
return( NULL );
}
*gr->rp.Layer = *newgr->rp->Layer; /* copy struct */
gr->rp.Layer->rp = &gr->rp; /* make this layer come back */
}
}
if( bm ) {
gr->rp.BitMap = bm;
}
gr->title = newgr->title;
gr->xtitle = newgr->xtitle;
gr->ytitle = newgr->ytitle;
gr->FPen = newgr->FPen;
gr->BPen = newgr->BPen;
gr->AxesPen = newgr->AxesPen;
gr->XlabPen = gr->YlabPen = gr->AxesPen;
gr->TitlePen = newgr->TitlePen;
gr->XtitlePen = gr->YtitlePen = gr->TitlePen;
gr->flags = newgr->flags;
gr->ctlflags = newgr->ctlflags;
if( newgr->titleta ) {
gr->titletf = gimmeFont( newgr->titleta );
}
if( newgr->xta ) {
gr->xlabtf = gr->xtf = gimmeFont( newgr->xta );
}
if( newgr->yta ) {
gr->ylabtf = gr->ytf = gimmeFont( newgr->yta );
}
if( !(gr->ctlflags & GGR_NOCLEARSTART) ) {
SetRast( &gr->rp, (long) gr->BPen );
}
initAxis( gr, &gr->X, &newgr->X );
initAxis( gr, &gr->Y, &newgr->Y );
SetAPen( &gr->rp, (long) gr->FPen );
SetBPen( &gr->rp, (long) gr->BPen );
SetDrMd( &gr->rp, (ULONG) JAM1 );
if( newgr->flags & (GGR_FILLTOX | GGR_FILLTOY) ) {
if( areainfo ) {
gr->rp.AreaInfo = areainfo;
} else if( !gr->rp.AreaInfo ) {
gr->rp.AreaInfo = chainAllocMem( &mymh,
(ULONG)sizeof(struct AreaInfo) + 5 * 2 * sizeof(LONG),
MEMF_PUBLIC | MEMF_CLEAR );
if( !gr->rp.AreaInfo ) {
chainFreeMem( mymh );
return( NULL );
}
InitArea( gr->rp.AreaInfo, (SHORT *)(gr->rp.AreaInfo + 1), 5L );
}
if( tmpras ) {
gr->rp.TmpRas = tmpras;
} else if( !gr->rp.TmpRas ) {
gr->rp.TmpRas = chainAllocMem( &mymh, (ULONG)sizeof(struct TmpRas),
MEMF_PUBLIC | MEMF_CLEAR );
if( !gr->rp.TmpRas ) {
chainFreeMem( mymh );
return( NULL );
}
width = gr->rp.BitMap->BytesPerRow << 3;
height = gr->rp.BitMap->Rows;
raster = chainAllocMem( &mymh,
(long)RASSIZE((long)width, (long)height),
MEMF_CHIP | MEMF_CLEAR );
if( !raster ) {
chainFreeMem( mymh );
return( NULL );
}
InitTmpRas( gr->rp.TmpRas, raster,
(long)RASSIZE((long)width, (long)height) );
}
}
if( !(gr->ctlflags & GGR_NOLABELS) ) {
drawGraphAxes( gr );
}
if( gr->ctlflags & (GGR_INITPOINT | GGR_INITORIGIN) ) {
gr->points = 1;
} else {
gr->points = 0;
}
gr->memhead = mymh;
return( gr );
} /* gimmeGraph */
short getRidOfGraph( gr )
GRAPH *gr;
{
#ifdef GIMME_WIMPY
if( !gr ) {
return( -1 );
}
#endif
if( gr->ctlflags & GGR_CLEARONEND ) {
clearGraph( gr );
}
if( gr->ytf ) {
getRidOfFont( gr->ytf );
}
if( gr->xtf ) {
getRidOfFont( gr->xtf );
}
if( gr->titletf ) {
getRidOfFont( gr->titletf );
}
chainFreeMem( gr->memhead );
return( 0 );
} /* getRidOfGraph */
VOID clearGraph( gr )
register GRAPH *gr;
{
BYTE fpen, bpen, axespen, titlepen;
BYTE xlabpen, ylabpen, xtitlepen, ytitlepen;
if( !(gr->ctlflags & GGR_NOCLEARSTART) ) {
SetRast( &gr->rp, (long) gr->BPen );
} else {
fpen = gr->FPen;
bpen = gr->BPen;
axespen = gr->AxesPen;
titlepen = gr->TitlePen;
xlabpen = gr->XlabPen;
ylabpen = gr->YlabPen;
xtitlepen = gr->XtitlePen;
ytitlepen = gr->YtitlePen;
gr->FPen = bpen;
gr->AxesPen = bpen;
gr->TitlePen = bpen;
gr->XlabPen = bpen;
gr->YlabPen = bpen;
gr->XtitlePen = bpen;
gr->YtitlePen = bpen;
SetAPen( &gr->rp, (long) bpen );
RectFill( &gr->rp, (long) TRANSX(gr,1), (long) TRANSY(gr,gr->Y.size),
(long) TRANSX(gr,gr->X.size), (long) TRANSY(gr,1) );
if( !(gr->ctlflags & GGR_NOLABELS) ) {
drawGraphAxes( gr );
}
gr->FPen = fpen;
gr->AxesPen = axespen;
gr->TitlePen = titlepen;
gr->XlabPen = xlabpen;
gr->YlabPen = ylabpen;
gr->XtitlePen = xtitlepen;
gr->YtitlePen = ytitlepen;
}
} /* clearGraph */
VOID resetGraph( gr )
register GRAPH *gr;
{
clearGraph( gr );
gr->X.low = gr->X.flow;
gr->X.high = gr->X.fhigh;
gr->X.lastdata = gr->X.fdata;
gr->X.lastoff = gr->X.foff;
gr->Y.low = gr->Y.flow;
gr->Y.high = gr->Y.fhigh;
gr->Y.lastdata = gr->Y.fdata;
gr->Y.lastoff = gr->Y.foff;
if( gr->ctlflags & (GGR_INITPOINT | GGR_INITORIGIN) ) {
gr->points = 1;
} else {
gr->points = 0;
}
if( !(gr->ctlflags & GGR_NOLABELS) ) {
drawGraphAxes( gr );
}
} /* resetGraph */
VOID drawGraphAxesOnly( gr )
register GRAPH *gr;
{
SHORT maxrastlen, maxlen;
SetAPen( &gr->rp, (long) gr->AxesPen );
Move( &gr->rp, (long) TRANSX(gr,0), (long) TRANSY(gr,gr->Y.size) );
Draw( &gr->rp, (long) TRANSX(gr,0), (long) TRANSY(gr,0) );
Draw( &gr->rp, (long) TRANSX(gr,gr->X.size), (long) TRANSY(gr,0) );
SetAPen( &gr->rp, (long) gr->FPen );
} /* drawGraphAxesOnly */
SHORT drawGraphAxes( gr )
register GRAPH *gr;
{
SHORT maxrastlen, maxlen;
SHORT yoff;
ULONG flags;
drawGraphAxesOnly( gr );
maxrastlen = graphWriteLabel( gr, GWL_XAXIS, gr->X.low, gr->X.high,
gr->X.step );
maxlen = graphWriteLabel( gr, GWL_YAXIS, gr->Y.low, gr->Y.high,
gr->Y.step );
drawGraphTitle( gr, gr->X.size >> 1, gr->Y.size + YLEEWAY,
GPT_XCENTRE | GPT_YBOTTOM );
yoff = - (YLEEWAY << 1);
if( !(gr->ctlflags & GGR_NOLABELS) ) {
yoff -= (gr->xlabtf ? gr->xlabtf->tf_YSize : gr->rp.TxHeight);
}
drawGraphXtitle( gr, gr->X.size >> 1, yoff, GPT_XCENTRE | GPT_YTOP );
flags = GPT_XCENTRE | GPT_YBOTTOM | GPT_YUPWARDS;
if( (gr->ctlflags & GGR_HIRES) && !(gr->ctlflags & GGR_INTERLACE) ) {
flags |= GPT_XTHICKEN;
}
drawGraphYtitle( gr, -maxlen - XLEEWAY*2, gr->Y.size >> 1, flags );
if( maxlen > maxrastlen ) {
maxrastlen = maxlen;
}
return( maxrastlen );
} /* drawGraphAxes */
VOID drawGraphTitle( gr, xoff, yoff, myflags )
register GRAPH *gr;
SHORT xoff, yoff;
ULONG myflags;
{
struct TextFont *tf;
if( gr->title ) {
tf = gr->rp.Font;
if( gr->titletf ) {
SetFont( &gr->rp, gr->titletf );
}
SetAPen( &gr->rp, (long) gr->TitlePen );
positionText( &gr->rp, myflags, gr->title, 0L,
TRANSX(gr,xoff), TRANSY(gr,yoff) );
SetAPen( &gr->rp, (long) gr->FPen );
if( gr->titletf && tf ) {
SetFont( &gr->rp, tf );
}
}
} /* drawGraphTitle */
VOID drawGraphXtitle( gr, xoff, yoff, myflags )
register GRAPH *gr;
SHORT xoff, yoff;
ULONG myflags;
{
struct TextFont *tf;
if( gr->xtitle ) {
tf = gr->rp.Font;
if( gr->xtf ) {
SetFont( &gr->rp, gr->xtf );
}
SetAPen( &gr->rp, (long) gr->XtitlePen );
positionText( &gr->rp, myflags, gr->xtitle, 0L,
TRANSX(gr,xoff), TRANSY(gr,yoff) );
SetAPen( &gr->rp, (long) gr->FPen );
if( gr->xtf && tf ) {
SetFont( &gr->rp, tf );
}
}
} /* drawGraphXtitle */
VOID drawGraphYtitle( gr, xoff, yoff, myflags )
register GRAPH *gr;
SHORT xoff, yoff;
ULONG myflags;
{
SHORT destx, desty;
struct TextFont *tf;
if( gr->ytitle ) {
tf = gr->rp.Font;
if( gr->ytf ) {
SetFont( &gr->rp, gr->ytf );
}
SetAPen( &gr->rp, (long) gr->YtitlePen );
positionText( &gr->rp, myflags, gr->ytitle, 0L,
TRANSX(gr,xoff), TRANSY(gr,yoff) );
SetAPen( &gr->rp, (long) gr->FPen );
if( gr->ytf && tf ) {
SetFont( &gr->rp, tf );
}
}
} /* drawGraphYtitle */
static SHORT coordToOffset( axis, coord )
register AXIS *axis;
SHORT coord;
{
if( axis->scale <= 0 ) {
return( SCALEUP(coord - axis->low) / -axis->scale );
} else {
return( SCALEDN((coord - axis->low) * axis->scale) );
}
} /* coordToOffset */
static SHORT offsetToCoord( axis, offset )
register AXIS *axis;
SHORT offset;
{
SHORT coord;
if( axis->scale <= 0 ) {
coord = SCALEDN(offset * -axis->scale);
} else {
/* offset in "window" belongs to next higher coordinate */
coord = (SCALEUP(offset) + axis->scale - 1) / axis->scale;
}
return( axis->low + coord );
} /* offsetToCoord */
/* internal use only!!
* initialize a graph's axis given a new axis structure
static VOID initAxis( gr, axis, nax )
GRAPH *gr;
register AXIS *axis;
register NEWAXIS *nax;
{
SHORT temp;
SHORT amt;
ULONG flags;
if( axis == &gr->X ) {
flags = gr->flags & GGR_X_FLAGS;
} else {
flags = gr->flags & GGR_Y_FLAGS;
}
axis->origin = nax->origin;
axis->size = nax->size;
axis->flow = axis->low = nax->low;
axis->step = nax->step;
axis->labnum = nax->labnum;
if( !nax->labdenom ) { /* to avoid divide by zero!! */
axis->labnum = 1;
axis->labdenom = 1;
} else {
axis->labdenom = nax->labdenom;
}
amt = nax->amt;
if( flags & (GGR_X_SPACING | GGR_Y_SPACING) ) {
if( !amt ) {
++amt;
}
axis->scale = SCALEUP(amt);
temp = axis->size;
do {
axis->high = offsetToCoord( axis, temp );
axis->usesize = coordToOffset( axis, axis->high );
} while( axis->usesize > temp-- );
} else {
if( flags & (GGR_X_INTERVALS | GGR_Y_INTERVALS) ) {
if( amt <= 0 ) {
amt = 5;
}
axis->high = axis->low + amt;
} else { /* if( flags & (GGR_X_MAX | GGR_Y_MAX) ) */
if( amt < axis->low ) {
amt = axis->low + 5;
}
axis->high = amt;
}
temp = axis->high - axis->low;
if( temp >= nax->size ) {
axis->scale = - ( SCALEUP(temp) / axis->size );
temp = SCALE - 1;
while( (axis->usesize = coordToOffset(axis, axis->high))
> axis->size ) {
if( temp < 0 ) break;
axis->scale -= SCALEUP(5) >> temp;
--temp;
} /* while */
if( flags & (GGR_X_INTEGRAL | GGR_DELTAX |
GGR_Y_INTEGRAL | GGR_DELTAY) ) {
if( (temp = SCALEUP(SCALEDN(-axis->scale))) < -axis->scale ) {
axis->scale = -SCALEUP( SCALEDN(-axis->scale) + 1 );
} else {
axis->scale = -temp;
}
}
} else {
axis->scale = SCALEUP(axis->size) / temp;
if( flags & (GGR_X_INTEGRAL | GGR_DELTAX |
GGR_Y_INTEGRAL | GGR_DELTAY) ) {
axis->scale = SCALEUP( SCALEDN(axis->scale) );
}
axis->usesize = coordToOffset( axis, axis->high );
}
}
axis->fhigh = axis->high;
if( gr->ctlflags & GGR_INITPOINT ) {
axis->lastdata = nax->initpt;
axis->lastoff = coordToOffset( axis, axis->lastdata );
} else { /* if( gr->ctlflags & GGR_INITORIGIN ) */
axis->lastdata = axis->low;
axis->lastoff = 1;
}
axis->fdata = axis->lastdata;
axis->foff = axis->lastoff;
if( !axis->scale ) {
axis->scale = 1; /* to avoid divide by zero!! */
}
} /* initAxis */
SHORT graphWriteLabel( gr, myflags, first, last, step )
register GRAPH *gr;
ULONG myflags;
SHORT first, last;
SHORT step;
{
AXIS *axis;
SHORT full, spacing;
SHORT low, high;
SHORT maxrlen = 0, len;
SHORT coord, loop;
SHORT x, y;
struct TextFont *tf;
BYTE xpen, ypen;
BYTE bpen, dmode;
if( !(myflags & GWL_NO_HIGH) ) {
if( myflags & (GWL_CLEAR_OLD | GWL_CLEAR_ONLY) ) {
if( myflags & GWL_XAXIS ) {
xpen = gr->XlabPen;
gr->XlabPen = gr->BPen;
} else {
ypen = gr->YlabPen;
gr->YlabPen = gr->BPen;
}
maxrlen = graphWriteLabel( gr,
myflags & ~(GWL_CLEAR_OLD | GWL_CLEAR_ONLY),
first, last, step );
if( myflags & GWL_XAXIS ) {
gr->XlabPen = xpen;
} else {
gr->YlabPen = ypen;
}
if( myflags & GWL_CLEAR_ONLY ) {
return( maxrlen );
}
}
tf = gr->rp.Font;
bpen = gr->rp.BgPen;
dmode = gr->rp.DrawMode;
if( myflags & GWL_XAXIS ) {
SetAPen( &gr->rp, (long) gr->XlabPen );
if( gr->xlabtf ) {
SetFont( &gr->rp, gr->xlabtf );
}
} else { /* else YAXIS */
SetAPen( &gr->rp, (long) gr->YlabPen );
if( gr->ylabtf ) {
SetFont( &gr->rp, gr->ylabtf );
}
}
}
if( step > 0 ) { /* if we want even-spaced labels */
for( loop = first; loop <= last; loop += step ) {
if( myflags & GWL_YAXIS) {
y = coordToOffset(&gr->Y, loop);
WritePixel( &gr->rp, (long)TRANSX(gr,-1), (long)TRANSY(gr,y) );
len = positionText( &gr->rp, GPT_XRIGHT | GPT_YCENTREBASE, NULL,
(long) (loop) * gr->Y.labnum / gr->Y.labdenom,
TRANSX(gr,-XLEEWAY), TRANSY(gr,y) );
} else { /* x-axis */
x = coordToOffset(&gr->X, loop);
WritePixel( &gr->rp, (long)TRANSX(gr,x), (long)TRANSY(gr,-1) );
len = positionText( &gr->rp, GPT_XCENTRE | GPT_YTOP, NULL,
(long) (loop) * gr->X.labnum / gr->X.labdenom,
TRANSX(gr,x), TRANSY(gr,-YLEEWAY) );
}
maxrlen = MAX(maxrlen, len);
} /* for */
} else {
if( myflags & GWL_YAXIS) {
high = coordToOffset(&gr->Y, last);
if( !(myflags & GWL_NO_HIGH) ) {
WritePixel( &gr->rp, (long)TRANSX(gr,-1),
(long)TRANSY(gr,high) );
maxrlen = positionText(&gr->rp, GPT_XRIGHT | GPT_YCENTREBASE,
NULL, (long) (last) * gr->Y.labnum / gr->Y.labdenom,
TRANSX(gr,-XLEEWAY), TRANSY(gr,high) );
}
low = coordToOffset(&gr->Y, first);
WritePixel( &gr->rp, (long)TRANSX(gr,-1), (long)TRANSY(gr,low) );
positionText( &gr->rp, GPT_XRIGHT | GPT_YCENTREBASE, NULL,
(long) (first) * gr->Y.labnum / gr->Y.labdenom,
TRANSX(gr,-XLEEWAY), TRANSY(gr,low) );
full = gr->rp.TxHeight;
axis = &gr->Y;
} else { /* x-axis */
high = coordToOffset(&gr->X, last);
if( !(myflags & GWL_NO_HIGH) ) {
WritePixel( &gr->rp, (long)TRANSX(gr,high),
(long)TRANSY(gr,-1) );
maxrlen = positionText( &gr->rp, GPT_XCENTRE| GPT_YTOP, NULL,
(long) (last) * gr->X.labnum / gr->X.labdenom,
TRANSX(gr,high), TRANSY(gr,-YLEEWAY) );
full = maxrlen;
myflags = (myflags & ~0xFFFFL) | full;
} else {
full = myflags & 0xFFFFL;
}
low = coordToOffset(&gr->X, first);
WritePixel( &gr->rp, (long)TRANSX(gr,low), (long)TRANSY(gr,-1) );
positionText( &gr->rp, GPT_XCENTRE | GPT_YTOP, NULL,
(long) (first) * gr->X.labnum / gr->X.labdenom,
TRANSX(gr,low), TRANSY(gr,-YLEEWAY) );
axis = &gr->X;
}
spacing = full << 1;
low += spacing;
coord = offsetToCoord( axis, low );
low = coordToOffset( axis, coord );
if( high - low >= spacing - TOLERANCE ) {
graphWriteLabel( gr, myflags | GWL_NO_HIGH, coord, last, step );
}
}
if( !(myflags & GWL_NO_HIGH) ) {
SetAPen( &gr->rp, (long) gr->FPen );
if( tf ) {
SetFont( &gr->rp, tf );
}
}
return( maxrlen );
} /* graphWriteLabel */
VOID addToGraph( gr, x, y )
register GRAPH *gr;
SHORT x, y;
{
SHORT amt;
SHORT newX, newY;
newX = updateCoord( gr, &gr->X, x );
newY = updateCoord( gr, &gr->Y, y );
SetAPen( &gr->rp, (long) gr->FPen );
if( !(gr->ctlflags & GGR_NOCONNECTLINE) ) {
Move( &gr->rp, (long) TRANSX(gr,gr->X.lastoff),
(long) TRANSY(gr,gr->Y.lastoff) );
Draw( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,newY) );
} else {
Move( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,newY) );
}
if( gr->flags & GGR_LINETOX ) {
Move( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,newY) );
Draw( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,1) );
}
if( gr->flags & GGR_LINETOY ) {
Move( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,newY) );
Draw( &gr->rp, (long)TRANSX(gr,1), (long)TRANSY(gr,newY) );
}
if( gr->flags & GGR_FILLTOX ) {
doBlock( &gr->rp, TRANSX(gr, gr->X.lastoff), TRANSY(gr, 1),
TRANSX(gr, gr->X.lastoff), TRANSY(gr, gr->Y.lastoff),
TRANSX(gr, newX), TRANSY(gr, newY),
TRANSX(gr, newX), TRANSY(gr, 1) );
}
if( gr->flags & GGR_FILLTOY ) {
doBlock( &gr->rp, TRANSX(gr, 1), TRANSY(gr, gr->Y.lastoff),
TRANSX(gr,gr->X.lastoff), TRANSY(gr, gr->Y.lastoff),
TRANSX(gr, newX), TRANSY(gr, newY),
TRANSX(gr, 1), TRANSY(gr, newY) );
}
if( gr->flags & GGR_BLACKTOX ) {
SetAPen( &gr->rp, (long) gr->BPen );
Move( &gr->rp, (long) TRANSX(gr, gr->X.lastoff),(long)TRANSY(gr, 1) );
Draw( &gr->rp, (long) TRANSX(gr, gr->X.lastoff),
(long) TRANSY(gr, gr->Y.lastoff) );
SetAPen( &gr->rp, (long) gr->FPen );
}
if( gr->flags & GGR_BLACKTOY ) {
SetAPen( &gr->rp, (long) gr->BPen );
Move(&gr->rp, (long) TRANSX(gr, 1),(long)TRANSY(gr, gr->Y.lastoff) );
Draw(&gr->rp, (long) TRANSX(gr, gr->X.lastoff),
(long) TRANSY(gr, gr->Y.lastoff) );
SetAPen( &gr->rp, (long) gr->FPen );
}
gr->X.lastoff = newX;
gr->Y.lastoff = newY;
++gr->points;
} /* addToGraph */
/* internal use only!!
* add a coordinate to an axis, doing the actual scrolling if necessary
* and updating some AXIS fields
*
* note: truncates to the rectangle defined by the origin and the axis' size.
*
* returns the standard pixel offset for the coordinate
static SHORT updateCoord( gr, axis, coord )
GRAPH *gr;
register AXIS *axis;
SHORT coord;
{
SHORT offset;
SHORT amt;
LONG Xamt, Yamt;
ULONG flags, awlflags;
if( axis == &gr->X ) {
flags = gr->flags & GGR_X_FLAGS;
} else {
flags = gr->flags & GGR_Y_FLAGS;
}
if( flags & (GGR_DELTAX | GGR_DELTAY) ) {
axis->lastdata += coord;
offset = coordToOffset( axis, axis->lastdata );
if( offset > axis->usesize ) {
if( axis == &gr->X ) {
Xamt = amt = offset - axis->lastoff;
Yamt = 0L;
} else {
Xamt = 0L;
Yamt = amt = offset - axis->lastoff;
}
ScrollRaster( &gr->rp, (long) Xamt, (long) Yamt,
(long) TRANSX(gr,1), (long) TRANSY(gr,gr->Y.size),
(long) TRANSX(gr,axis->size), (long) TRANSY(gr,1) );
awlflags = (axis == &gr->X) ? GWL_XAXIS : GWL_YAXIS;
if( !(gr->ctlflags & GGR_NOLABELS) ) {
graphWriteLabel( gr, awlflags | GWL_CLEAR_ONLY, axis->low,
axis->high, axis->step );
}
axis->low += coord;
axis->high += coord;
/* drawGraphAxesOnly( gr ); */
if( !(gr->ctlflags & GGR_NOLABELS) ) {
graphWriteLabel( gr, awlflags, axis->low, axis->high,
axis->step );
}
offset = axis->lastoff;
axis->lastoff -= amt;
}
} else {
offset = coordToOffset( axis, coord );
if( offset < 0 ) {
offset = 0;
} else if( offset > axis->size ) {
offset = axis->size;
}
axis->lastdata = coord;
}
return( offset );
} /* updateCoord */
/* internal use only!!
* do an area fill on the 4 pairs of coordinates,
* clipped to the rastport's bitmap size
* NOTE: the TmpRas should be (at least) the same size as this bitmap
static VOID doBlock( rp, x1, y1, x2, y2, x3, y3, x4, y4 )
register struct RastPort *rp;
SHORT x1, y1, x2, y2, x3, y3, x4, y4;
{
SHORT width, height;
width = rp->BitMap->BytesPerRow << 3;
height = rp->BitMap->Rows;
if( x1 < 0 ) x1 = 0;
else if( x1 > width ) x1 = width;
if( x2 < 0 ) x2 = 0;
else if( x2 > width ) x2 = width;
if( x3 < 0 ) x3 = 0;
else if( x3 > width ) x3 = width;
if( x4 < 0 ) x4 = 0;
else if( x4 > width ) x4 = width;
if( x1 == x3 ) return;
if( y1 < 0 ) y1 = 0;
else if( y1 > height ) y1 = height;
if( y2 < 0 ) y2 = 0;
else if( y2 > height ) y2 = height;
if( y3 < 0 ) y3 = 0;
else if( y3 > height ) y3 = height;
if( y4 < 0 ) y4 = 0;
else if( y4 > height ) y4 = height;
if( y1 == y3 ) return;
AreaMove( rp, (long) x1, (long) y1 );
AreaDraw( rp, (long) x2, (long) y2 );
AreaDraw( rp, (long) x3, (long) y3 );
AreaDraw( rp, (long) x4, (long) y4 );
AreaEnd( rp );
} /* doBlock */
SHAR_EOF
cat << \SHAR_EOF > inputhand.c
/*
* FILE: inputhand.c
* Support routines for installing/removing an input handler.
*
* Public Domain, but keep my name in it as the original author.
* 31-Oct-88 Jan Sven Trabandt added to gimme.lib
*/
#define I_AM_INPUTHAND
#include "gimmelib/gimmefuncs.h"
struct IOStdReq *addInputHandler( handler, data, pri, name )
void (*handler)();
APTR data;
BYTE pri;
UBYTE *name;
{
struct MsgPort *port;
struct IOStdReq *ioreq;
struct Interrupt *handint;
#ifdef GIMME_WIMPY
if( !handler ) {
return( NULL );
}
#endif
if( !(port = CreatePort(NULL, 0L)) ) {
return( NULL );
}
if( !(ioreq = CreateStdIO(port)) ) {
DeletePort( port );
return( NULL );
}
if( !(handint = AllocMem((ULONG)sizeof(struct Interrupt),
MEMF_PUBLIC | MEMF_CLEAR)) ) {
DeleteStdIO( ioreq );
DeletePort( port );
return( NULL );
}
handint->is_Data = data;
handint->is_Code = handler;
handint->is_Node.ln_Type = NT_MESSAGE;
handint->is_Node.ln_Pri = pri;
handint->is_Node.ln_Name = (char *) name;
if( OpenDevice("input.device", 0L, ioreq, 0L) ) {
FreeMem( handint, (ULONG)sizeof(struct Interrupt) );
DeleteStdIO( ioreq );
DeletePort( port );
return( NULL );
}
ioreq->io_Command = IND_ADDHANDLER;
ioreq->io_Data = (APTR) handint;
ioreq->io_Length = sizeof(struct Interrupt);
if( DoIO(ioreq) ) {
CloseDevice( ioreq );
FreeMem( handint, (ULONG)sizeof(struct Interrupt) );
DeleteStdIO( ioreq );
DeletePort( port );
return( NULL );
}
return( ioreq );
} /* addInputHandler */
short removeInputHandler( ioreq )
struct IOStdReq *ioreq;
{
#ifdef GIMME_WIMPY
if( !ioreq ) {
return( -1 );
}
#endif
ioreq->io_Command = IND_REMHANDLER;
ioreq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
if( DoIO(ioreq) ) {
return( -1 );
}
CloseDevice( ioreq );
FreeMem( ioreq->io_Data, (ULONG)sizeof(struct Interrupt) );
DeletePort( ioreq->io_Message.mn_ReplyPort );
DeleteStdIO( ioreq );
return( 0 );
} /* removeInputHandler */
SHAR_EOF
cat << \SHAR_EOF > intuistuff.c
/*
* FILE: intuistuff.c
* Support routines for creating some useful intuition-type structures.
*
* Public Domain, but keep my name in it as the original author.
* 31-Aug-88 Jan Sven Trabandt first release version
* 31-Oct-88 Jan Sven Trabandt made gimmeBorder more flexible/efficient
*/
#define I_AM_INTUISTUFF
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/intuistuff.h"
#include "gimmelib/macros.h"
/* WSL-type construct */
#define GUESS do {
#define QUIF( cond ) if( cond ) break;
#define ENDGUESS } while( 0 );
struct Border *gimmeBorder( mh, xsize, ysize )
void **mh;
SHORT xsize, ysize;
{
register struct Border *bp;
register SHORT *r;
ULONG size;
void *mymh = NULL;
void **mhdr = &mymh;
GUESS
size = sizeof(struct Border);
if( !mh ) {
r = AllocMem( (ULONG)sizeof(SHORT) * 2 * 5, MEMF_PUBLIC );
QUIF( !r );
mhdr = NULL;
} else {
if( xsize > 0 && ysize > 0 ) {
/* need room for 5 pairs of shorts as well */
size = sizeof(struct Border) + sizeof(SHORT) * 2 * 5;
r = NULL;
}
}
bp = chainAllocMem( mhdr, (ULONG) size, MEMF_CLEAR | MEMF_PUBLIC );
QUIF( !bp );
bp->FrontPen = 1;
bp->DrawMode = JAM1;
if( xsize > 0 && ysize > 0 ) {
if( !r ) {
r = (SHORT *) (bp + 1);
}
bp->XY = r;
r[2] = r[4] = xsize - 1;
r[5] = r[7] = ysize - 1;
bp->Count = 5;
}
linkChainMem( mh, mymh );
return( bp );
ENDGUESS
if( mhdr ) {
chainFreeMem( mymh );
} else {
if( r ) {
FreeMem( r, (ULONG) sizeof(SHORT) * 2 * 5 );
}
}
return( NULL );
} /* gimmeBorder */
struct Image *gimmeImage( mh, depth, width, height )
void **mh;
SHORT depth, width, height;
{
register struct Image *ip;
ULONG size; /* image datasize (bytes) for allocation */
void *mymh = NULL;
void **mhdr = &mymh;
UBYTE planepick;
GUESS
if( !mh ) {
mhdr = NULL;
}
ip = chainAllocMem( mhdr, (ULONG)sizeof(struct Image),
MEMF_CLEAR | MEMF_PUBLIC );
QUIF( !ip );
ip->Width = width;
ip->Height = height;
ip->Depth = depth;
if( depth > 0 && width > 0 && height > 0 ) {
size = GIM_IMAGESIZE(depth, width, height);
ip->ImageData = chainAllocMem( mhdr, size, MEMF_CLEAR|MEMF_CHIP );
QUIF( !ip->ImageData );
planepick = 1;
while( --depth > 0 ) {
planepick = (planepick << 1) + 1;
} /* while */
ip->PlanePick = planepick;
}
linkChainMem( mh, mymh );
return( ip );
ENDGUESS
if( mhdr ) {
chainFreeMem( mymh );
} else {
if( ip ) {
FreeMem( ip, (ULONG)sizeof(struct Image) );
}
}
return( NULL );
} /* gimmeImage */
struct IntuiText *gimmeIntuiText( mh, s, textattr, width )
void **mh;
UBYTE *s;
struct TextAttr *textattr;
SHORT width;
{
register struct IntuiText *itp;
GUESS
itp = chainAllocMem( mh, (ULONG)sizeof(struct IntuiText),
MEMF_CLEAR | MEMF_PUBLIC );
QUIF( !itp );
itp->FrontPen = 1;
itp->DrawMode = JAM2;
itp->ITextFont = textattr;
itp->IText = s;
if( width > 0 ) { /* if width given, centre text */
itp->LeftEdge = (width - IntuiTextLength(itp)) >> 1;
}
return( itp );
ENDGUESS
return( NULL );
} /* gimmeIntuiText */
SHAR_EOF
cat << \SHAR_EOF > keyboard.c
/*
* FILE: keyboard.c
* Support routines for "cooking" raw input.
*
* Public Domain, but keep my name in it as the original author.
* 31-Aug-88 Jan Sven Trabandt first release version
*/
#include "gimmelib/gimmefuncs.h"
SHORT deadKeyConvert( imsg, buf, bufsize, keymap )
struct IntuiMessage *imsg;
UBYTE *buf;
USHORT bufsize;
struct KeyMap *keymap;
{
struct InputEvent ievent;
#ifdef GIMME_WIMPY
if( !imsg || !buf || bufsize < 0 ) {
return( -3 );
}
#endif
if( imsg->Class != RAWKEY ) {
return( -2 );
}
ievent.ie_NextEvent = NULL;
ievent.ie_Class = IECLASS_RAWKEY;
ievent.ie_Code = imsg->Code;
ievent.ie_Qualifier = imsg->Qualifier;
ievent.ie_position.ie_addr = *((APTR *)imsg->IAddress);
return( RawKeyConvert(&ievent, buf, (ULONG)bufsize, keymap) );
} /* deadKeyConvert */
SHAR_EOF
cat << \SHAR_EOF > memchain.c
/*
* FILE: memchain.c
* Support routines for chaining memory, anchored to a head which
* points to the latest chunk of memory allocated.
*
* Public Domain, but keep my name in it as the original author.
* 31-Aug-88 Jan Sven Trabandt first release version
* 31-Oct-88 Jan Sven Trabandt chainAllocMem acts like normal AllocMem
* if no memory-chain pointer given
* parameters checked in all these functions
*/
#include "gimmelib/gimmefuncs.h"
struct memnode {
struct memnode *next;
ULONG size;
};
void *chainAllocMem( headptr, size, type )
struct memnode **headptr;
ULONG size;
ULONG type;
{
register struct memnode *p;
if( !headptr ) {
p = AllocMem( size, type );
} else {
size += sizeof(struct memnode);
if( p = AllocMem(size, type) ) {
p->size = size;
p->next = *headptr;
*headptr = p;
++p; /* make p point to user's memory */
}
}
return( p );
} /* chainAllocMem */
VOID chainFreeMem( head )
register struct memnode *head;
{
struct memnode *p;
while( head ) {
p = head->next;
FreeMem( head, head->size );
head = p;
}
} /* chainFreeMem */
short linkChainMem( headptr, head )
struct memnode **headptr;
struct memnode *head;
{
register struct memnode *p;
if( headptr && head ) {
p = head;
if( *headptr ) {
for( ; p->next; p = p->next ) {
} /* for */
p->next = *headptr;
}
*headptr = head;
}
return( 0 );
} /* linkChainMem */
short pluckChainMem( headptr, mem )
struct memnode **headptr;
void *mem;
{
register struct memnode *p;
struct memnode *mine;
if( !headptr ) {
return( -1 );
}
if( mem && *headptr ) {
mine = (struct memnode *)( ((UBYTE *) mem) -
(ULONG)sizeof(struct memnode) );
if( mine == *headptr ) {
*headptr = mine->next;
} else {
for( p = *headptr; p->next != mine; p = p->next ) {
if( !p->next ) {
return( -1 ); /* not in this chain */
}
} /* for */
p->next = mine->next;
}
FreeMem( mine, mine->size );
}
return( 0 );
} /* pluckChainMem */
SHAR_EOF
cat << \SHAR_EOF > menu.c
/*
* FILE: menu.c
* Support routines for creating menu and menu item structures.
*
* Public Domain, but keep my name in it as the original author.
* 31-Oct-88 Jan Sven Trabandt added to gimme.lib
*/
#define I_AM_MENU
#include "gimmelib/gimmefuncs.h"
#define GIM_BUILTIN
#include "gimmelib/macros.h"
extern struct GfxBase *GfxBase;
#define XLEEWAY 10 /* make menu item a little visually appealing */
struct Menu *gimmeMenu( mhptr, left, width, name, flags )
void **mhptr;
SHORT left, width;
UBYTE *name;
ULONG flags;
{
register struct Menu *menu;
if( menu = chainAllocMem(mhptr, (ULONG)sizeof(struct Menu),
MEMF_PUBLIC | MEMF_CLEAR) ) {
menu->LeftEdge = left;
if( width >= 0 ) {
menu->Width = width;
} else {
menu->Width = 9 * strlen( name );
}
menu->Height = 9; /* currently ignored by Intuition */
menu->Flags = flags;
menu->MenuName = (BYTE *) name;
}
return( menu );
} /* gimmeMenu */
struct MenuItem *gimmeMenuItem( mhptr, left, width, height, command, name,
textattr, flags )
void **mhptr;
SHORT left;
SHORT width, height;
BYTE command;
UBYTE *name;
struct TextAttr *textattr;
ULONG flags;
{
register struct MenuItem *item;
SHORT temp;
void *mymh = NULL;
GUESS
QUIF( !mhptr );
item = chainAllocMem( &mymh, (ULONG)sizeof(struct MenuItem),
MEMF_PUBLIC | MEMF_CLEAR );
QUIF( !item );
if( flags & ITEMTEXT ) {
item->ItemFill = (APTR) gimmeIntuiText( &mymh, name, textattr, 0 );
QUIF( !item->ItemFill );
((struct IntuiText *)item->ItemFill)->DrawMode |= INVERSVID;
if( width < 0 ) {
width = IntuiTextLength( item->ItemFill ) + XLEEWAY;
}
if( height < 0 ) {
if( textattr ) {
height = textattr->ta_YSize;
} else {
height = GfxBase->DefaultFont->tf_YSize;
}
}
} else {
item->ItemFill = (APTR) name;
if( flags & HIGHIMAGE ) {
item->SelectFill = (APTR) textattr;
}
if( width < 0 ) {
if( (struct Image *) name ) {
width = ((struct Image *)name)->Width;
}
if( (struct Image *) item->SelectFill ) {
temp = ((struct Image *)item->SelectFill)->Width;
if( temp > width ) {
width = temp;
}
}
}
if( height < 0 ) {
if( (struct Image *) name ) {
height = ((struct Image *)name)->Height;
}
if( (struct Image *) item->SelectFill ) {
temp = ((struct Image *)item->SelectFill)->Height;
if( temp > height ) {
height = temp;
}
}
}
}
if( flags & CHECKIT ) {
width += CHECKWIDTH;
}
if( flags & COMMSEQ ) {
width += COMMWIDTH + 4; /* separate text/image from commseq */
}
item->LeftEdge = left;
item->Width = width;
item->Height = height;
item->Flags = flags;
item->Command = command;
linkChainMem( mhptr, mymh );
return( item );
ENDGUESS
if( mymh ) {
chainFreeMem( mymh );
}
return( NULL );
} /* gimmeMenuItem */
SHAR_EOF
cat << \SHAR_EOF > menustuff.c
/*
* FILE: menustuff.c
* Support routines for dealing with menus and menuitems.
*
* NOTE: these routines should only be used on a menustrip that is
* not attached to a window or guaranteed not to be actively used by
* Intuition (eg. by using the MENUVERIFY flag).
*
* Public Domain, but keep my name in it as the original author.
* 31-Oct-88 Jan Sven Trabandt added to gimme.lib
*/
#define I_AM_MENUSTUFF
#include "gimmelib/gimmefuncs.h"
#include "gimmelib/menustuff.h"
/* internal flags: must stay within defined GMI_RESERVED bits */
#define GMI_SUBITEM (1L << 30) /* process subitem, not item */
#define GMI_DO_TOP (1L << 29) /* modify top edge */
#define GMI_DO_ME (1L << 28) /* modify mutual exclude */
#define GMI_SNEAKY (1L << 27) /* sneaky -- don't modify too much */
#define GMI_ADJUST (GMI_FIXUP | GMI_SHUFFLE)
#define GMI_ADJUSTME (GMI_FIXUPME | GMI_SHUFFLEME)
ULONG addMenuItem( menu, item, positem, possub, numitem, myflags )
struct Menu *menu;
struct MenuItem *item;
SHORT positem, possub, numitem;
ULONG myflags;
{
register struct MenuItem *temp, **old;
struct MenuItem *save, *savelast;
SHORT pos, sub;
SHORT top, topedge;
if( !menu || !item || !numitem ) {
return( MENUNULL );
}
if( myflags & GMI_SUBITEM ) {
old = &((struct MenuItem *)menu)->SubItem;
} else {
old = &menu->FirstItem;
}
if( myflags & GMI_ADDSUBITEM ) {
if( !*old ) { /* if no items, can't put subitem */
return( MENUNULL );
}
} else {
/* find last item in list to be added and truncate list appropriately */
for( temp = item; temp->NextItem; temp = temp->NextItem ) {
if( --numitem == 0 ) {
temp->NextItem = NULL;
break;
}
} /* for */
savelast = temp; /* save pointer to last item to be added */
if( positem == 0 || !*old ) { /* add as first (sub)item */
savelast->NextItem = *old;
*old = item;
if( *old && (myflags & (GMI_ADJUST|GMI_ADJUSTME|GMI_APPEAREND)) ) {
pos = 0;
save = item;
myflags |= GMI_SNEAKY; /* careful handling */
goto calculate_adjustment_mi;
}
adjustMenuItems( item, savelast->NextItem, 0, 0, myflags );
return( SHIFTITEM(0) | SHIFTSUB(NOSUB) );
}
}
/* find the item preceding where to insert, and position# for new item */
pos = 1;
for( temp = *old; temp->NextItem; temp = temp->NextItem ) {
if( --positem == 0 ) {
break;
}
++pos;
} /* for */
if( myflags & GMI_ADDSUBITEM ) {
sub = ITEMNUM( addMenuItem(temp, item, possub, 0, numitem,
(myflags | GMI_SUBITEM) & ~GMI_ADDSUBITEM) );
} else {
savelast->NextItem = temp->NextItem;
save = temp; /* save ptr to item after which to add */
if( myflags & (GMI_ADJUST | GMI_ADJUSTME) ) {
calculate_adjustment_mi: {}
/* calculate top edge for new item */
topedge = 0;
for( temp = *old; temp; temp = temp->NextItem ) {
top = temp->TopEdge + temp->Height;
if( temp == save ) {
if( !(myflags & GMI_SNEAKY) ) {
save->NextItem = item;
if( top > topedge ) {
topedge = top;
}
}
if( !(myflags & GMI_APPEAREND) ) {
break; /* exit for loop */
}
temp = savelast; /* skip over what we added */
}
if( top > topedge ) {
topedge = top;
}
} /* for */
adjustMenuItems( item, savelast->NextItem, topedge, pos, myflags );
} else {
save->NextItem = item;
}
sub = NOSUB;
}
return( SHIFTITEM(pos) | SHIFTSUB(sub) );
} /* addMenuItem */
ULONG addMenu( menuptr, menu, posmenu, nummenu, myflags )
struct Menu **menuptr;
struct Menu *menu;
SHORT posmenu, nummenu;
ULONG myflags;
{
register struct Menu *temp, **old;
struct Menu *save, *savelast;
SHORT pos;
SHORT left, leftedge;
if( !nummenu || !menuptr || !menu ) {
return( MENUNULL );
}
old = menuptr;
/* find last menu in list to be added and truncate list appropriately */
for( temp = menu; temp->NextMenu; temp = temp->NextMenu ) {
if( --nummenu == 0 ) {
temp->NextMenu = NULL;
break;
}
} /* for */
savelast = temp; /* save pointer to last menu to be added */
if( posmenu == 0 || !*old ) { /* add to front of menu strip */
savelast->NextMenu = *old;
*old = menu;
if( *old && (myflags & (GMI_ADJUST | GMI_APPEAREND)) ) {
pos = 0;
save = menu;
myflags |= GMI_SNEAKY; /* careful handling */
goto calculate_adjustment_m;
}
adjustMenuLefts( menu, savelast->NextMenu, 0, myflags );
return( SHIFTMENU(0) | SHIFTITEM(NOITEM) | SHIFTSUB(NOSUB) );
}
/* find the menu preceding where to insert, and position# for new menu */
pos = 1;
for( temp = *old; temp->NextMenu; temp = temp->NextMenu ) {
if( --posmenu == 0 ) {
break;
}
++pos;
} /* for */
savelast->NextMenu = temp->NextMenu;
save = temp; /* save ptr to menu after which to add */
if( myflags & (GMI_ADJUST | GMI_ADJUSTME) ) {
calculate_adjustment_m: {}
/* calculate left edge for new menu */
leftedge = 0;
for( temp = *old; temp; temp = temp->NextMenu ) {
left = temp->LeftEdge + temp->Width;
if( temp == save ) {
if( !(myflags & GMI_SNEAKY) ) {
save->NextMenu = menu;
if( left > leftedge ) {
leftedge = left;
}
}
if( !(myflags & GMI_APPEAREND) ) {
break; /* exit for loop */
}
temp = savelast; /* skip over what we added */
}
if( left > leftedge ) {
leftedge = left;
}
} /* for */
adjustMenuLefts( menu, savelast->NextMenu, leftedge, myflags );
} else {
save->NextMenu = menu;
}
return( SHIFTMENU(pos) | SHIFTITEM(NOITEM) | SHIFTSUB(NOSUB) );
} /* addMenu */
struct MenuItem *removeMenuItem( menu, item, positem, possub, numitem, myflags )
struct Menu *menu;
struct MenuItem *item;
SHORT positem, possub, numitem;
ULONG myflags;
{
register struct MenuItem *temp, **old;
struct MenuItem *save;
SHORT pos; /* position for mutual exclude */
if( !menu ) {
return( NULL );
}
if( myflags & GMI_SUBITEM ) {
old = &((struct MenuItem *)menu)->SubItem;
} else {
old = &menu->FirstItem;
}
if( !*old || !numitem ) { /* if no menu items */
return( NULL );
}
if( myflags & GMI_REMSUBITEM ) {
save = item; /* don't want to check item address yet */
item = NULL;
} else {
if( item ) {
positem = -1;
}
}
pos = 0;
temp = *old;
if( temp != item && positem != 0 && temp->NextItem ) {
/* find the "item" preceding where to remove */
for( ; temp->NextItem && --positem != 0; ) {
++pos;
if( temp->NextItem == item ) { /* found the item */
break;
}
temp = temp->NextItem; /* next in loop */
if( !temp->NextItem ) { /* no more to follow so stop */
break;
}
} /* for */
old = &temp->NextItem;
}
/* now old points to a MenuItem pointer to item to be removed */
if( item && *old != item ) { /* if its not the right item */
return( NULL );
}
if( myflags & GMI_REMSUBITEM ) {
item = removeMenuItem( temp, save, possub, 0, numitem,
(myflags | GMI_SUBITEM) & ~GMI_REMSUBITEM );
} else {
if( !item ) {
item = *old;
}
if( myflags & GMI_ADDRONLY ) {
return( item );
}
/* find last one to be removed */
for( temp = item; temp->NextItem; temp = temp->NextItem ) {
if( --numitem == 0 ) {
break;
}
} /* for */
*old = temp->NextItem;
temp->NextItem = NULL;
myflags &= ~(GMI_FIXUP | GMI_FIXUPME);
if( myflags & GMI_SHUFFLE ) {
myflags |= GMI_FIXUP;
}
if( myflags & GMI_SHUFFLEME ) {
myflags |= GMI_FIXUPME;
}
adjustMenuItems( *old, NULL, item->TopEdge, pos, myflags );
}
return( item );
} /* removeMenuItem */
struct Menu *removeMenu( menuptr, menu, posmenu, nummenu, myflags )
struct Menu **menuptr;
struct Menu *menu;
SHORT posmenu, nummenu;
ULONG myflags;
{
register struct Menu *temp, **old;
if( !nummenu || !menuptr || !*menuptr ) {
return( NULL );
}
old = menuptr;
if( menu ) {
posmenu = -1;
}
temp = *old;
if( temp != menu && posmenu != 0 && temp->NextMenu ) {
/* find the menu preceding where to remove */
for( ; temp->NextMenu && --posmenu != 0; ) {
if( temp->NextMenu == menu ) { /* found the menu */
break;
}
temp = temp->NextMenu; /* next in loop */
if( !temp->NextMenu ) { /* no more to follow so stop */
break;
}
} /* for */
old = &temp->NextMenu;
}
/* now old points to a Menu pointer to menu to be removed */
if( menu && *old != menu ) { /* if its not the right menu */
return( NULL );
}
if( !menu ) {
menu = *old;
}
if( myflags & GMI_ADDRONLY ) {
return( menu );
}
/* find last one to be removed */
for( temp = menu; temp->NextMenu; temp = temp->NextMenu ) {
if( --nummenu == 0 ) {
break;
}
} /* for */
*old = temp->NextMenu;
temp->NextMenu = NULL;
adjustMenuLefts( *old, NULL, menu->LeftEdge, myflags );
return( menu );
} /* removeMenu */
short adjustMenuItems( item, stop, topedge, meposition, myflags )
struct MenuItem *item, *stop;
SHORT topedge, meposition;
register ULONG myflags;
{
register struct MenuItem *temp;
if( !(myflags & (GMI_ADJUST | GMI_ADJUSTME)) ) {
return( -1 );
}
if( myflags & GMI_FIXUP ) {
myflags |= GMI_DO_TOP;
}
if( myflags & GMI_FIXUPME ) {
myflags |= GMI_DO_ME;
}
for( temp = item; temp; temp = temp->NextItem ) {
if( temp == stop ) {
if( !(myflags & (GMI_SHUFFLE | GMI_SHUFFLEME)) ) {
break;
}
myflags &= ~(GMI_DO_TOP | GMI_DO_ME);
if( (myflags & GMI_SHUFFLE) && !(myflags & GMI_APPEAREND) ) {
myflags |= GMI_DO_TOP;
}
if( myflags & GMI_SHUFFLEME ) {
myflags |= GMI_DO_ME;
}
}
if( myflags & GMI_DO_TOP ) {
temp->TopEdge = topedge;
}
topedge += temp->Height;
if( myflags & GMI_DO_ME ) {
temp->MutualExclude = ~(1L << meposition);
}
++meposition;
} /* for */
return( 0 );
} /* adjustMenuItems */
short adjustMenuLefts( menu, stop, leftedge, myflags )
struct Menu *menu, *stop;
register SHORT leftedge;
ULONG myflags;
{
register struct Menu *temp;
if( !(myflags & (GMI_ADJUST)) ) {
return( -1 );
}
for( temp = menu; temp; temp = temp->NextMenu ) {
if( !(myflags & GMI_SHUFFLE) && temp == stop ) {
break;
}
temp->LeftEdge = leftedge;
leftedge += temp->Width;
} /* for */
return( 0 );
} /* adjustMenuLefts */
SHAR_EOF
cat << \SHAR_EOF > message.c
/*
* FILE: message.c
* Support routines for dynamic (de)allocation of [extended] message structs
*
* Public Domain, but keep my name in it as the original author.
* 31-Aug-88 Jan Sven Trabandt first release version
*/
#include "gimmelib/gimmefuncs.h"
struct Message *gimmeMessage( size, replyport )
ULONG size;
struct MsgPort *replyport;
{
struct Message *msg;
#ifdef GIMME_WIMPY
if( size > 0x0FFFFL ) {
return( NULL );
}
#endif
msg = (struct Message *) AllocMem( size, MEMF_PUBLIC );
if( msg ) {
msg->mn_Node.ln_Type = NT_FREEMSG;
msg->mn_Node.ln_Pri = 0;
msg->mn_Node.ln_Name = NULL;
msg->mn_ReplyPort = replyport;
msg->mn_Length = size;
}
return( msg );
} /* gimmeMessage */
short getRidOfMessage( msg )
struct Message *msg;
{
#ifdef GIMME_WIMPY
if( !msg || !msg->mn_Length > 0 ) {
return( -1 );
}
#endif
FreeMem( msg, (ULONG) msg->mn_Length );
} /* getRidOfMessage */
SHAR_EOF
# End of shell archive
exit 0
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.